package br.com.fatec.cqr.view;

import java.awt.Event;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;

import javax.crypto.spec.PSource;
import javax.swing.AbstractAction;
import javax.swing.InputMap;
import javax.swing.JEditorPane;
import javax.swing.JTabbedPane;
import javax.swing.KeyStroke;
import javax.swing.event.UndoableEditEvent;
import javax.swing.event.UndoableEditListener;
import javax.swing.undo.CannotRedoException;
import javax.swing.undo.CannotUndoException;
import javax.swing.undo.UndoManager;

public class EditorPane extends JEditorPane {

	private UndoAction undoAction = new UndoAction();
	private RedoAction redoAction = new RedoAction();
	private UndoManager undo = new UndoManager();
	private PontoVirgula pontoVirgula = new PontoVirgula();

	/**
	 * Descricao: Metodo utilizado para chamada do metodo configurar Mapa
	 *  
	 */
	public EditorPane() {
		this.getDocument()
				.addUndoableEditListener(new MyUndoableEditListener());
		configurarMapa(this);
	}

	/**
	 * Descricao: Metodo usado para implementar os comandos Undo e Redo alem
	 * da implementacao do uso do ponto e virgula.
	 * 
	 * @param jeditorPane
	 */
	private void configurarMapa(JEditorPane jeditorPane) {
		InputMap inputMap = jeditorPane.getInputMap();

		// Ctrl-z desfaz
		KeyStroke key = KeyStroke.getKeyStroke(KeyEvent.VK_Z, Event.CTRL_MASK);
		inputMap.put(key, undoAction);

		// Ctrl-y refaz
		key = KeyStroke.getKeyStroke(KeyEvent.VK_Y, Event.CTRL_MASK);
		inputMap.put(key, redoAction);


		key = KeyStroke.getKeyStroke((char) KeyEvent.VK_SEMICOLON);
		inputMap.put(key, pontoVirgula);
	}

	/**
	 * Descricao: Chamadas do metodo de undo e redo.
	 *
	 */
	private class MyUndoableEditListener implements UndoableEditListener {

		@Override
		public void undoableEditHappened(UndoableEditEvent e) {
			// Remember the edit and update the menus
			undo.addEdit(e.getEdit());
			undoAction.updateUndoState();
			redoAction.updateRedoState();
		}

	}
	
	/**
	 * Classe filha privada PontoVirgula
	 */
	private class PontoVirgula extends AbstractAction {

		@Override
		/**
		 * Descricao: Metodo ponto e virgula
		 * 
		 */
		public void actionPerformed(ActionEvent e) {
			String texto = getText() + ";";
			setText(texto);
			JTabbedPane query = PainelSql.query;
			EditorPane display = PainelSql.display;
			JEditorPane displayNoSql = PainelNoSql.displayNoSql;
			new Action().runAction(query, display, displayNoSql);
		}

	}
	
	/**
	 * Classe filha privada undo
	 * 
	 */
	private class UndoAction extends AbstractAction {

		private UndoAction() {
			setEnabled(false);
		}

		@Override
		/**
		 * Descricao: Metodo para realizacao do undo
		 */
		public void actionPerformed(ActionEvent e) {

			try {
				undo.undo();
			} catch (CannotUndoException ex) {
			}
			updateUndoState();
			redoAction.updateRedoState();

		}

		/**
		 * Descricao: Realiza o controle do status do 
		 * botao Undo.
		 */
		private void updateUndoState() {
			if (undo.canUndo()) {
				setEnabled(true);
			} else {
			}
		}

	}

	/**
	 * Classe filha privada RedoAction
	 *
	 */
	private class RedoAction extends AbstractAction {

		private RedoAction() {
			setEnabled(false);
		}

		@Override
		/**
		 * Descricao: Realiza o controle do status do 
		 * botao Redo.
		 */
		public void actionPerformed(ActionEvent e) {

			try {
				undo.redo();
			} catch (CannotRedoException ex) {
			}
			updateRedoState();
			undoAction.updateUndoState();

		}

		/* Controla Status do btnRedo */
		/**
		 * Descricao: Metodo que realiza o controle do botao
		 * Redo.
		 */
		private void updateRedoState() {
			if (undo.canRedo()) {
				setEnabled(true);
			} else {
				setEnabled(false);
			}
		}

	}

}
